package services.application;

import dto.app.*;
import dto.retjson.PageDataDto;
import models.application.*;
import models.pubobj.AniObjectState;
import models.pubobj.AniObjectType;
import models.user.AniUser;
import services.exception.AniDataException;
import utils.AniGeneralUtils;
import utils.AniMapBuilder;
import utils.MVCUtils;

import java.util.*;

/**
 * User: yeh
 * Date: 1/29/13
 * Time: 6:34 PM
 * For:  wilddragon
 */
public class AniAppQueryService extends AniAppService{
    public static AppInfoDto queryAppWithId(Long id, AniUser curUser){
        List<AniApp> resultApp = new ArrayList<AniApp>();
        resultApp.add(AniAppService.getApp(new AniApp(id)));
        List<AppInfoDto> resultAppDtos = getAppDtoList(
                resultApp,
                curUser
        );
        if(resultAppDtos.isEmpty()){
            throw new AniDataException("TARGET_APP_NOT_EXISTS");
        }
        resultAppDtos.get(0).setApiInfoList();
        return resultAppDtos.get(0);
    }
    public static List<AppInfoDto> queryPublicApps(
            AniUser curUser,
            AniAppClassification classification,
            String keyword,
            Integer page
    ){
        //query elements
        Map queryElements = new AniMapBuilder<String, Object>()
                .put("appClassification", classification)
                .getMap();
        //capsule app list
        List<AniApp> resultApps = AniApp.queryPublicApps(queryElements, keyword, page);

        return getAppDtoList(resultApps, curUser);
    }
    private static List<AppInfoDto> getAppDtoList(List<AniApp> appDaoList, AniUser curUser){
        List<AppInfoDto> resultDtoList = new ArrayList<AppInfoDto>();
        Map<Long, AniApp> userApps = AniUserAppRel.getInstalledAppsMap(appDaoList, curUser);
        for(AniApp oneAppDao: appDaoList){
            if(curUser.id == oneAppDao.ownerUser.id){
                resultDtoList.add(
                        PrivateAppInfoDto.generateFromDao(oneAppDao, curUser, userApps.get(oneAppDao.id) != null)
                );
            } else{
                resultDtoList.add(
                        PublicAppInfoDto.generateFromDao(oneAppDao, userApps.get(oneAppDao.id) != null, curUser)
                );
            }
        }
        return resultDtoList;
    }

    public static PageDataDto queryUserOwnedApps(
            AniUser curUser,
            AniAppClassification classification,
            AniObjectType type,
            AniObjectState state,
            AniApp parent,
            String keyword,
            Integer page
    ){
        //query elements
        Map queryElements = new AniMapBuilder<String, Object>()
                .put("appClassification.id", classification.id)
                .put("type.id", type.id)
                .put("state.id", state.id)
                .put("relyOn.id", parent.id)
                .getMap();
        return new PageDataDto(
                AniApp.queryUserOwnedAppTotalSize(
                        queryElements,
                        keyword,
                        curUser
                ),
                Integer.parseInt(MVCUtils.getConfig("wd.page.size")),
                generatePrivateAppDtoListFromDao(
                        curUser,
                        AniApp.queryUserOwnedApp(
                            queryElements,
                            keyword,
                            curUser,
                            page
                    )
                )
        );
    }
    public static PageDataDto queryUserInstalledApps(
            AniUser curUser,
            AniAppClassification classification,
            AniApp parent,
            String keyword,
            Integer page
    ){
        Map queryElements = new AniMapBuilder<String, Object>()
                .put("targetApp.appClassification.id", classification.id)
                .put("targetApp.relyOn.id", parent.id)
                .getMap();

        List<PublicAppInfoDto> appsDtoList = generateInstalledAppDtoListFromRel(
                AniUserAppRel.searchUserInstalledApp(
                        curUser,
                        queryElements,
                        keyword,
                        page
                ),
                curUser
        );
        return new PageDataDto(
                AniUserAppRel.searchUserInstalledAppTotalCount(
                        curUser,
                        queryElements,
                        keyword
                ),
                Integer.parseInt(MVCUtils.getConfig("wd.page.size")),
                appsDtoList
        );
    }
    private static List<PrivateAppInfoDto> generatePrivateAppDtoListFromDao(AniUser curUser, List<AniApp> privateAppsDaoList){
        List<PrivateAppInfoDto> appInfoDtos = new ArrayList<PrivateAppInfoDto>();
        if(!privateAppsDaoList.isEmpty()){
            for(AniApp onePrivateApp: privateAppsDaoList){
                appInfoDtos.add(
                        PrivateAppInfoDto.generateFromDao(
                                onePrivateApp,
                                curUser,
                                AniAppInstallService.isAllAppInstalled(
                                        AniGeneralUtils.obtainSingleObjList(onePrivateApp),
                                        curUser
                                )
                        )
                );
            }
        }
        return appInfoDtos;
    }
    private static List<PublicAppInfoDto> generateInstalledAppDtoListFromRel(List<AniUserAppRel> userAppRelList, AniUser oneUser){
        List<PublicAppInfoDto> resultDtoList = new ArrayList<PublicAppInfoDto>();
        if(!userAppRelList.isEmpty()){
            for(AniUserAppRel oneAppRelDao: userAppRelList){
                resultDtoList.add(
                        PublicAppInfoDto.generateFromDao(oneAppRelDao.targetApp, true, oneUser)
                );
            }
        }
        return resultDtoList;
    }

    private static PublicAppInfoDto generatePublicAppDtoFromAppDaoWithUser(AniApp oneApp, AniUser oneUser){
        return PublicAppInfoDto.generateFromDao(
                oneApp,
                AniAppInstallService.isAllAppInstalled(
                        AniGeneralUtils.obtainSingleObjList(oneApp),
                        oneUser
                ),
                oneUser
        );
    }
}
